/*
 * program_macros.h -- this file is part of mISPL.
 * Copyright (C) 2011 Christian Krause
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
#ifndef PROGRAM_MACROS_H_
#define PROGRAM_MACROS_H_

#include "program.h"

/*** Accessing instructions ***/
#define GET_INS(p,i)		((p->commands[i]>>8) & 0xFF)
#define SET_INS(p,i,ins)	(p->commands[i] = (((ins & 0xFF)<<8) | GET_OPS(p,i)))

/*** Accessing both operands ***/
#define GET_OPS(p,i)		(p->commands[i] & 0xFF)
#define SET_OPS(p,i,ops)	(p->commands[i] = ((GET_INS(p,i)<<8) | (ops & 0xFF)))

/*** Accessing the first operand ***/
#define GET_OP1(p,i)		((p->commands[i]>>4) & 0x0F)
#define SET_OP1(p,i,op1)	(SET_OPS(p,i,((op1 & 0x0F)<<4) | GET_OP2(p,i)))

/*** Accessing the second operand ***/
#define GET_OP2(p,i)		((p->commands[i] & 0x0F))
#define SET_OP2(p,i,op2)	(SET_OPS(p,i,(GET_OP1(p,i)<<4) | (op2 & 0x0F)))
#define GET_OP2_CONST(p,i)	((p->commands[i] & 0b1000) ? \
								-((int) (p->commands[i] & 0b0111)) : \
								 ((int) (p->commands[i] & 0b0111)))

/*** Setting commands ***/
#define SET_COM(p,i,ins,op1,op2) (p->commands[i] = ((ins & 0xFF)<<8) | ((op1 & 0x0F)<<4) | (op2 & 0x0F))

/*** Instruction meta-information ***/
#define INS_WITH_OP2_CONSTANT(x) (x==SET || (x>=SKE && x<=SKG))
#define INS_WITH_OP2_NIL(x) (x==LPB || x==LPE)
#define INS_WITH_OP2_REGISTER(x) (!IS_OP2_CONSTANT(x) && !IS_OP2_NIL(x))

#endif /* PROGRAM_MACROS_H_ */
